
#include "mbclient.h"
#include <QDebug>
#include <QDateTime>
#include <QModbusDataUnit>
#include <QModbusDevice>
#include <QModbusTcpClient>
#include <QUrl>

ModbusClient::ModbusClient(QObject *parent)
    : QObject(parent)
    , modbusClient(nullptr)
    , m_status("Disconnected")
    , m_reading(false)
{
    // 创建Modbus客户端实例
    modbusClient = new QModbusTcpClient(this);
    
    // 连接信号
    connect(modbusClient, &QModbusClient::stateChanged,
            this, &ModbusClient::handleConnectionStateChanged);
    connect(modbusClient, &QModbusClient::errorOccurred,
            this, &ModbusClient::handleDeviceError);

    // 创建定时器
    readTimer = new QTimer(this);
    connect(readTimer, &QTimer::timeout, this, &ModbusClient::readAllData);

    // 创建超时定时器
    timeoutTimer = new QTimer(this);
    timeoutTimer->setSingleShot(true);
    connect(timeoutTimer, &QTimer::timeout, this, &ModbusClient::onReadTimeout);
}

ModbusClient::~ModbusClient()
{
    if (modbusClient) {
        modbusClient->disconnectDevice();
        delete modbusClient;
    }
}

bool ModbusClient::connectToServer(const QString& address, int port)
{
    if (!modbusClient) {
        return false;
    }

    if (modbusClient->state() != QModbusDevice::ConnectedState) {
        modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
        modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, address);

        if (!modbusClient->connectDevice()) {
            setStatus("Connection failed");
            return false;
        }

        setStatus("Connecting...");
        return true;
    }
    return false;
}

void ModbusClient::disconnectFromServer()
{
    if (modbusClient) {
        stopReadTimer();
        modbusClient->disconnectDevice();
        setStatus("Disconnected");
        emit connectedChanged();
    }
}

void ModbusClient::readAllData()
{
    if (!modbusClient || modbusClient->state() != QModbusDevice::ConnectedState || m_reading) {
        qDebug() << "[Client] Cannot read data - Client state:" 
                 << (modbusClient ? modbusClient->state() : -1)
                 << "Reading:" << m_reading;
        return;
    }

    m_reading = true;
    qDebug() << "[Client] Starting data read operation";

    // 创建读取请求
    QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, TOTAL_REGS);
    
    if (QModbusReply *reply = modbusClient->sendReadRequest(readUnit, 1)) {
        qDebug() << "[Client] Read request sent, waiting for response";
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, &ModbusClient::handleReadReady);
            timeoutTimer->start(1000); // 1秒超时
            timeoutTimer->start(6000); // 设置6秒超时
            qDebug() << "[Client] Read request pending, timeout timer started";
        } else {
            delete reply;
            qDebug() << "[Client] Read request finished immediately";
            reply->deleteLater();
            m_reading = false;
        }
    } else {
        qDebug() << "[Client] Error: Failed to send read request:" << modbusClient->errorString();
        m_reading = false;
        emit errorOccurred(tr("Read error: ") + modbusClient->errorString());
    }
}

void ModbusClient::handleReadReady()
{
    timeoutTimer->stop();
    QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
    if (!reply) {
        qDebug() << "[Client] Error: Invalid reply object";
        m_reading = false;
        return;
    }

    if (reply->error() == QModbusDevice::NoError) {
        const QModbusDataUnit unit = reply->result();
        qDebug() << "[Client] Read response received successfully"
                 << "Type:" << unit.registerType()
                 << "Address:" << unit.startAddress()
                 << "Count:" << unit.valueCount();
        processReadResult(unit);
        emit readCompleted();
    } else {
        emit errorOccurred(tr("Read response error: %1 (code: 0x%2)").arg(reply->errorString()).arg(reply->error(), -1, 16));
        qDebug() << "[Client] Read response error:" << reply->errorString()
                 << "Error code:" << reply->error();
        emit errorOccurred(tr("Read response error: %1 (code: 0x%2)")
                         .arg(reply->errorString())
                         .arg(reply->error(), -1, 16));
    }

    reply->deleteLater();
    m_reading = false;
}

void ModbusClient::processReadResult(const QModbusDataUnit& unit)
{
    const QVector<quint16> values = unit.values();
    
    if (values.size() < TOTAL_REGS) {
        emit errorOccurred("Received incomplete data");
        return;
    }

    // ID
    m_deviceData.id = values[REG_ID];

    // Name
    m_deviceData.name = registersToString(&values[REG_NAME], 10);

    // Value
    m_deviceData.value = registersToFloat(values[REG_VALUE], values[REG_VALUE + 1]);

    // Status
    m_deviceData.status = values[REG_STATUS] != 0;

    // Timestamp
    m_deviceData.timestamp = registersToInt32(values[REG_TIMESTAMP], values[REG_TIMESTAMP + 1]);

    // Temperature
    m_deviceData.temperature = registersToFloat(values[REG_TEMPERATURE], values[REG_TEMPERATURE + 1]);

    // Humidity
    m_deviceData.humidity = registersToFloat(values[REG_HUMIDITY], values[REG_HUMIDITY + 1]);

    // Pressure
    m_deviceData.pressure = values[REG_PRESSURE];

    // Alarm Status
    m_deviceData.alarmStatus = values[REG_ALARM];

    // Description
    m_deviceData.description = registersToString(&values[REG_DESC], 15);

    emit deviceDataChanged();
}

// 写入设备ID
void ModbusClient::writeDeviceId(int id)
{
    QVector<quint16> values(1);
    values[0] = static_cast<quint16>(id);
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_ID, values);
}

// 写入设备名称
void ModbusClient::writeDeviceName(const QString& name)
{
    QVector<quint16> values(10, 0);
    stringToRegisters(name, values.data(), 10);
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_NAME, values);
}

// 写入设备值
void ModbusClient::writeDeviceValue(float value)
{
    QVector<quint16> values(2);
    quint16 reg1, reg2;
    floatToRegisters(value, reg1, reg2);
    values[0] = reg1;
    values[1] = reg2;
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_VALUE, values);
}

// 写入设备状态
void ModbusClient::writeDeviceStatus(bool status)
{
    QVector<quint16> values(1);
    values[0] = status ? 1 : 0;
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_STATUS, values);
}

// 写入温度
void ModbusClient::writeTemperature(float temp)
{
    QVector<quint16> values(2);
    quint16 reg1, reg2;
    floatToRegisters(temp, reg1, reg2);
    values[0] = reg1;
    values[1] = reg2;
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_TEMPERATURE, values);
}

// 写入湿度
void ModbusClient::writeHumidity(float humidity)
{
    QVector<quint16> values(2);
    quint16 reg1, reg2;
    floatToRegisters(humidity, reg1, reg2);
    values[0] = reg1;
    values[1] = reg2;
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_HUMIDITY, values);
}

// 写入压力
void ModbusClient::writePressure(int pressure)
{
    QVector<quint16> values(1);
    values[0] = static_cast<quint16>(pressure);
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_PRESSURE, values);
}

// 写入报警状态
void ModbusClient::writeAlarmStatus(int status)
{
    QVector<quint16> values(1);
    values[0] = static_cast<quint16>(status);
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_ALARM, values);
}

// 写入描述
void ModbusClient::writeDescription(const QString& description)
{
    QVector<quint16> values(15, 0);
    stringToRegisters(description, values.data(), 15);
    sendWriteRequest(QModbusDataUnit::HoldingRegisters, REG_DESC, values);
}

void ModbusClient::sendWriteRequest(QModbusDataUnit::RegisterType type, int address, const QVector<quint16>& values)
{
    if (!modbusClient || modbusClient->state() != QModbusDevice::ConnectedState) {
        emit errorOccurred(tr("Not connected"));
        return;
    }

    QModbusDataUnit writeUnit(type, address, values);
    if (QModbusReply *reply = modbusClient->sendWriteRequest(writeUnit, 1)) {
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, [this, reply]() {
                handleWriteReply(reply);
            });
        } else {
            reply->deleteLater();
        }
    } else {
        emit errorOccurred(tr("Write error: ") + modbusClient->errorString());
    }
}

void ModbusClient::handleWriteReply(QModbusReply* reply)
{
    if (!reply) {
        return;
    }

    if (reply->error() == QModbusDevice::NoError) {
        emit writeCompleted();
        // 暂停定时器
        stopReadTimer();
        // 等待一段时间后再恢复读取
        QTimer::singleShot(500, this, [this]() {
            readAllData();  // 读取一次最新数据
            startReadTimer(); // 恢复定时器
        });
    } else {
        emit errorOccurred(tr("Write response error: %1 (code: 0x%2)")
            .arg(reply->errorString())
            .arg(reply->error(), -1, 16));
    }

    reply->deleteLater();
}

void ModbusClient::handleConnectionStateChanged()
{
    qDebug() << "[Client] Connection state changed to:" << modbusClient->state();
    
    if (modbusClient->state() == QModbusDevice::ConnectedState) {
        setStatus("Connected");
        startReadTimer();
        // 连接成功后等待一段时间再读取数据
        qDebug() << "[Client] Scheduling initial data read";
        QTimer::singleShot(1000, this, &ModbusClient::readAllData);
    } else {
        setStatus("Disconnected");
        stopReadTimer();
    }
    emit connectedChanged();
}

void ModbusClient::handleDeviceError(QModbusDevice::Error error)
{
    Q_UNUSED(error)
    QString errorString = modbusClient->errorString();
    qDebug() << "Modbus client error:" << errorString;
    emit errorOccurred(errorString);
    setStatus("Error: " + errorString);
}

void ModbusClient::onReadTimeout()
{
    qDebug() << "[Client] Read operation timed out";
    m_reading = false;
    emit errorOccurred("Read operation timed out");
}

bool ModbusClient::isConnected() const
{
    return modbusClient && modbusClient->state() == QModbusDevice::ConnectedState;
}

QString ModbusClient::status() const
{
    return m_status;
}

void ModbusClient::setStatus(const QString& status)
{
    if (m_status != status) {
        m_status = status;
        emit statusChanged();
    }
}

void ModbusClient::startReadTimer()
{
    readTimer->start(1000);  // 每秒读取一次
}

void ModbusClient::stopReadTimer()
{
    readTimer->stop();
}
